package managedbean.stakeholder;

import entity.AddressEntity;
import entity.BranchEntity;
import entity.FnBBranchEntity;
import entity.FnBIOTREntity;
import entity.IndustryTypeEntity;
import entity.PackagePurchasedEntity;
import entity.PaymentItemEntity;
import entity.PaymentManagementEntity;
import entity.ServicePackageEntity;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.ejb.EJB;
import session.stateful.StakeholderSessionBeanStateful;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import exception.ChangeServicePackageException;
import exception.StakeholderBizRegNumberExist;
import exception.StakeholderEmailExist;
import exception.StakeholderUsernameExist;
import java.util.List;
import entity.StakeholderEntity;
import java.io.IOException;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import javax.faces.event.PhaseEvent;
import org.primefaces.event.SelectEvent;
import session.stateful.BranchSessionBeanStateful;
import session.stateful.ServiceSessionBean;
import exception.ExtendServicePackageException;
import exception.TerminateServicePackageException;
import java.security.SecureRandom;
import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import javax.faces.component.UIComponent;
import javax.faces.event.ActionEvent;
import javax.faces.validator.ValidatorException;
import javax.mail.MessagingException;
import session.stateful.EmailSessionBean;
import session.stateful.TableSessionBean;
import session.stateful.TransactionSessionBean;

/**
 *
 * @author Dell
 */
@ManagedBean(name = "stakeholderManagerBean")
@SessionScoped
public class StakeholderManagerBean implements Serializable {

    @EJB
    private StakeholderSessionBeanStateful stakeholderSessionBean;
    @EJB
    private BranchSessionBeanStateful branchSessionBean;
    @EJB
    private ServiceSessionBean serviceSessionBean;
    @EJB
    private TableSessionBean tableSessionBean;
    @EJB
    private EmailSessionBean eMailSessionBean;
    @EJB
    private TransactionSessionBean transactionSessionBean;
    private String statusMessage;
    private Date dateExpired;
    private int numOfMonth;
    private int numOfMonthExtend;
    private AddressEntity stakeholderAddress;
    private AddressEntity branchAddress;
    private StakeholderEntity stakeholder;
    private FnBBranchEntity selectedBranch;
    private IndustryTypeEntity industryType;
    private ServicePackageEntity selectedServicePackage;
    private PackagePurchasedEntity currentServicePackage;
    private List<IndustryTypeEntity> industryTypeList;
    private List<FnBBranchEntity> fnBBranchList;
    private List<BranchEntity> branchList;
    private FnBIOTREntity fnBIOTR;
    private SecureRandom random;
    private List<StakeholderEntity> stakeholders;
    //Dat
    private String retypedPassword;
    private String message;
    //Thai Duy
    private String oldPassword;
    private String newPassword;
    private String retypeNewPassword;
    private List<PaymentItemEntity> paymentItemList;
    private Date date1;
    private Date date2;
    private String outstandingBillAmount;
    private boolean addBranch;
    //Vu
    private PackagePurchasedEntity nextServicePackage;
    
    public StakeholderManagerBean() {
        stakeholderAddress = new AddressEntity();
        branchAddress = new AddressEntity();
        stakeholder = new StakeholderEntity();
        selectedBranch = new FnBBranchEntity();
        fnBBranchList = new ArrayList<FnBBranchEntity>();
        fnBIOTR = new FnBIOTREntity();
        random = new SecureRandom();
        stakeholders = new ArrayList<StakeholderEntity>();
        stakeholder.setAddress(new AddressEntity());
        addBranch = true;
    }

    public void initAddBranch(PhaseEvent event) {
        if (addBranch) {
            selectedBranch = new FnBBranchEntity();
            fnBIOTR =  new FnBIOTREntity();
            branchAddress = new AddressEntity();
            addBranch = false;
        }
    }
    public void register(ActionEvent event) throws UnsupportedEncodingException, NoSuchAlgorithmException {

        if (getStakeholder().getCorpEmail().indexOf("@") == -1) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_ERROR, "Email address must contains @", ""));
            return;

        }

        try {
            String encryptedPassword = encrypt(stakeholder.getPassword());
            stakeholder.setPassword(encryptedPassword);
            stakeholderSessionBean.addNewStakeholder(stakeholder, stakeholderAddress, industryType);
            stakeholder = new StakeholderEntity();
            stakeholderAddress = new AddressEntity();

            setStatusMessage("New stakeholder added successfully");
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_INFO, "Add New Stakeholder Result: " + getStatusMessage(), ""));
        } catch (StakeholderUsernameExist ex) {
            setStatusMessage(ex.getMessage());
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_ERROR, "Add New Stakeholder Result: " + getStatusMessage(), ""));
        } catch (StakeholderEmailExist ex) {
            setStatusMessage(ex.getMessage());
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_ERROR, "Add New Stakeholder Result: " + getStatusMessage(), ""));
        } catch (StakeholderBizRegNumberExist ex) {
            setStatusMessage(ex.getMessage());
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_ERROR, "Add New Stakeholder Result: " + getStatusMessage(), ""));
        }
    }

    public void createNewBranch() {
        branchSessionBean.createNewBranch(stakeholder, selectedBranch, branchAddress, fnBIOTR);
        addBranch = true;
        
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_INFO, "Add New Branch Succesfully", ""));
    }

    public void initBranchList(PhaseEvent event) throws IOException {
        if (!checkStakeholder()) {
            return;
        }

        branchList = branchSessionBean.getAllBranchByStakeholderId(stakeholder.getId());
        fnBBranchList = new ArrayList<FnBBranchEntity>();
        for (BranchEntity obj : branchList) {
            if (obj instanceof FnBBranchEntity) {
                fnBBranchList.add((FnBBranchEntity) obj);
            }
        }
    }

    public void initIndustryType(PhaseEvent event) {
        industryTypeList = stakeholderSessionBean.getIndustryTypeList();
    }

    public void initPackagePurchased(PhaseEvent event) throws IOException {
        if (!checkBranch()) {
            return;
        }
        currentServicePackage = branchSessionBean.getCurrentPackagePurchased(selectedBranch.getId());
        nextServicePackage=branchSessionBean.getNextPackagePurchased(selectedBranch.getId());
    }

    public void initEditBranchInfo(PhaseEvent event) throws IOException {
        if (!checkBranch()) {
            return;
        }
        addBranch = true;
    }

    public void editInfo(ActionEvent event) {
        stakeholderSessionBean.editStakeholderInfo(stakeholder);
        FacesMessage msg = new FacesMessage("You have successfully changed your info");
        FacesContext.getCurrentInstance().addMessage(null, msg);

    }

    public void retrieveStakeholderInfo() {
        stakeholder = stakeholderSessionBean.retrieveStakeholderInfoByUsername(stakeholder.getUsername());
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("stakeholder", stakeholder);
        System.out.println("FINISH");
    }

    public List<StakeholderEntity> getStakeholders() {
        return stakeholderSessionBean.getAllStakeholders();
    }

    public String onRowSelectNavigateFnBBranch(SelectEvent event) {
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("selectedBranch", selectedBranch);
        return "stakeholder/StakeholderEditBranchInfo?faces-redirect=true";
    }

    public StakeholderEntity getSelectedStakeholder() {
        return stakeholder;
    }

    public void setSelectedStakeholder(StakeholderEntity stakeholder) {
        this.stakeholder = stakeholder;
    }

    public void editStakeholderInfo() {
        stakeholderSessionBean.editStakeholderInfo(stakeholder);
    }

    public void editBranchInfo() {
        branchSessionBean.editBranchInfo(getSelectedBranch());
    }

    public List<ServicePackageEntity> getServicePackages() {
        return serviceSessionBean.getServicePackagesForStakeholder();
    }

    public PackagePurchasedEntity getPackagePurchased() {
        return branchSessionBean.getLatestPackagedPurchasedByBranchId(selectedBranch.getId());
    }

    public void branchPurchaseServicePackage(ActionEvent event) {
        try {
            branchSessionBean.changeCurrentPackage(selectedBranch.getId(), selectedServicePackage.getId(), numOfMonth);
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_INFO, "You have successfully changed your service package", ""));
        } catch (ChangeServicePackageException ex) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_ERROR, "Error: " + ex.getMessage(), ""));
        }
    }

    public void branchExtendServicePackage(ActionEvent event) {
        try {
            branchSessionBean.extendCurrentPackage(selectedBranch.getId(), numOfMonthExtend);
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_INFO, "You have successfully extended your service package", ""));
        } catch (ExtendServicePackageException ex) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_ERROR, "Error: " + ex.getMessage(), ""));
        }
    }

    public void branchTerminateServicePackage(ActionEvent event) {
        try {
            branchSessionBean.terminateCurrentPackage(selectedBranch.getId(),true);
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_INFO, "You have successfully terminated your service package", ""));
        } catch (TerminateServicePackageException ex) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_ERROR, "Error: " + ex.getMessage(), ""));
        }
    }

    // This method is created by Dat, used for validating password
    public void validatePassword(FacesContext facesContext, UIComponent arg1, Object value) throws ValidatorException {
        String inputPassword = (String) value;
        if (!stakeholder.getPassword().equals(inputPassword)) {
            FacesMessage msg = new FacesMessage("The passwords you entered do not match. Please try again.");
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            throw new ValidatorException(msg);
        }
    }

    public StakeholderSessionBeanStateful getStakeholderSessionBean() {
        return stakeholderSessionBean;
    }

    public void setStakeholderSessionBean(StakeholderSessionBeanStateful stakeholderSessionBean) {
        this.stakeholderSessionBean = stakeholderSessionBean;
    }

    public BranchSessionBeanStateful getBranchSessionBean() {
        return branchSessionBean;
    }

    public void setBranchSessionBean(BranchSessionBeanStateful branchSessionBean) {
        this.branchSessionBean = branchSessionBean;
    }

    public ServiceSessionBean getServiceSessionBean() {
        return serviceSessionBean;
    }

    public void setServiceSessionBean(ServiceSessionBean serviceSessionBean) {
        this.serviceSessionBean = serviceSessionBean;
    }

    public String getStatusMessage() {
        return statusMessage;
    }

    public void setStatusMessage(String statusMessage) {
        this.statusMessage = statusMessage;
    }

    public Date getDateExpired() {
        return dateExpired;
    }

    public void setDateExpired(Date dateExpired) {
        this.dateExpired = dateExpired;
    }

    public int getNumOfMonth() {
        return numOfMonth;
    }

    public void setNumOfMonth(int numOfMonth) {
        this.numOfMonth = numOfMonth;
    }

    public int getNumOfMonthExtend() {
        return numOfMonthExtend;
    }

    public void setNumOfMonthExtend(int numOfMonthExtend) {
        this.numOfMonthExtend = numOfMonthExtend;
    }

    public FnBBranchEntity getSelectedBranch() {
        return selectedBranch;
    }

    public void setSelectedBranch(FnBBranchEntity selectedBranch) {
        this.selectedBranch = selectedBranch;
    }

    public ServicePackageEntity getSelectedServicePackage() {
        return selectedServicePackage;
    }

    public void setSelectedServicePackage(ServicePackageEntity selectedServicePackage) {
        this.selectedServicePackage = selectedServicePackage;
    }

    public PackagePurchasedEntity getCurrentServicePackage() {
        return currentServicePackage;
    }

    public void setCurrentServicePackage(PackagePurchasedEntity currentServicePackage) {
        this.currentServicePackage = currentServicePackage;
    }

    public List<FnBBranchEntity> getFnBBranchList() {
        return fnBBranchList;
    }

    public void setFnBBranchList(List<FnBBranchEntity> fnBBranchList) {
        this.fnBBranchList = fnBBranchList;
    }

    public List<BranchEntity> getBranchList() {
        return branchList;
    }

    public void setBranchList(List<BranchEntity> branchList) {
        this.branchList = branchList;
    }

    public AddressEntity getStakeholderAddress() {
        return stakeholderAddress;
    }

    public void setStakeholderAddress(AddressEntity stakeholderAddress) {
        this.stakeholderAddress = stakeholderAddress;
    }

    public AddressEntity getBranchAddress() {
        return branchAddress;
    }

    public void setBranchAddress(AddressEntity branchAddress) {
        this.branchAddress = branchAddress;
    }

    public StakeholderEntity getStakeholder() {
        return stakeholder;
    }

    public void setStakeholder(StakeholderEntity stakeholder) {
        this.stakeholder = stakeholder;
    }

    public IndustryTypeEntity getIndustryType() {
        return industryType;
    }

    public void setIndustryType(IndustryTypeEntity industryType) {
        this.industryType = industryType;
    }

    public List<IndustryTypeEntity> getIndustryTypeList() {
        return industryTypeList;
    }

    public void setIndustryTypeList(List<IndustryTypeEntity> industryTypeList) {
        this.industryTypeList = industryTypeList;
    }

    public FnBIOTREntity getFnBIOTR() {
        return fnBIOTR;
    }

    public void setFnBIOTR(FnBIOTREntity fnBIOTR) {
        this.fnBIOTR = fnBIOTR;
    }

    public void search() {
        int check = 8;
        String condition = "SELECT s FROM StakeholderEntity s WHERE ";
        String st1 = "", st2 = "", st3 = "", st4 = "", st5 = "", st6 = "", st7 = "", st8 = "";

        if (stakeholder.getId() == null) {
            check--;
        } else {
            st1 = "s.id LIKE '%" + stakeholder.getId() + "%' AND ";
        }
        if (stakeholder.getUsername() == null) {
            check--;
        } else {
            st2 = "s.username LIKE '%" + stakeholder.getUsername() + "%' AND ";
        }
        if (stakeholder.getCorpName() == null) {
            check--;
        } else {
            st3 = "s.corpName LIKE '%" + stakeholder.getCorpName() + "%' AND ";
        }
        if (stakeholder.getBizRegNumber() == null) {
            check--;
        } else {
            st4 = "s.bizRegNumber LIKE '%" + stakeholder.getBizRegNumber() + "%' AND ";
        }
        if (stakeholder.getAddress().getStreetName() == null) {
            check--;
        } else {
            st5 = "s.address LIKE '%" + stakeholder.getAddress().getStreetName() + "%' AND ";
        }
        if (stakeholder.getCorpContactNumber() == null) {
            check--;
        } else {
            st6 = "s.phoneNumber LIKE '%" + stakeholder.getCorpContactNumber() + "%' AND ";
        }
        if (stakeholder.getCorpEmail() == null) {
            check--;
        } else {
            st7 = "s.email LIKE '%" + stakeholder.getCorpEmail() + "%' AND ";
        }
        if (stakeholder.getCorpFaxNumber() == null) {
            check--;
        } else {
            st8 = "s.fax LIKE '%" + stakeholder.getCorpFaxNumber() + "%' AND ";
        }

        if (check == 0) {
            condition = condition.substring(0, condition.indexOf("WHERE"));
        } else {
            condition = condition + st1 + st2 + st3 + st4 + st5 + st6 + st7 + st8;
            condition = condition.substring(0, condition.indexOf("AND"));
        }
        stakeholders = stakeholderSessionBean.getStakeholders(condition);
    }

    public String getRetypedPassword() {
        return retypedPassword;
    }

    public void setRetypedPassword(String retypedPassword) {
        this.retypedPassword = retypedPassword;
    }
    // This part is added by Cong Dat
    private List<PaymentManagementEntity> paymentManagementList;

    public List<PaymentManagementEntity> getPaymentManagementList() {
        return paymentManagementList;
    }

    public void setPaymentManagementList(List<PaymentManagementEntity> paymentManagementList) {
        this.paymentManagementList = paymentManagementList;
    }

    public boolean checkStakeholder() throws IOException {
        stakeholder = (StakeholderEntity) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("stakeholder");
        if (stakeholder == null || stakeholder.getId() == null) {
            stakeholder = new StakeholderEntity();
            FacesContext.getCurrentInstance().getExternalContext().redirect("stakeholder/StakeholderLogin.xhtml");
            return false;
        }
        return true;
    }

    public boolean checkBranch() throws IOException {
        if (!checkStakeholder()) {
            return false;
        }

        selectedBranch = (FnBBranchEntity) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("selectedBranch");
        if (selectedBranch == null || selectedBranch.getId() == null) {
            FacesContext.getCurrentInstance().getExternalContext().redirect("stakeholder/StakeholderViewAllBranch.xhtml");
            return false;
        }
        return true;
    }

    /* Thai Duy*/
    public String randomString() {
        String generatedString = new BigInteger(100, getRandom()).toString(32);
        return generatedString;
    }

    public String encrypt(String inputString) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        String outputString = util.encryption.PasswordService.getInstance().encrypt(inputString);
        return outputString;
    }

    public boolean validateSamePassword() {
        if (getRetypeNewPassword().equals(getNewPassword())) {
            return true;
        } else {
            return false;
        }
    }

    public void changePassword() throws UnsupportedEncodingException, NoSuchAlgorithmException {
        String encryptedOldPassword = encrypt(getOldPassword());
        String encryptedNewPassword = encrypt(getNewPassword());
        if (encryptedOldPassword.equals(getSelectedStakeholder().getPassword())) {
            if (!validateSamePassword()) {
                FacesContext.getCurrentInstance().addMessage(getRetypeNewPassword(), new FacesMessage(
                        FacesMessage.SEVERITY_ERROR, "Passwords are not the same", "Passwords are not the same"));
            } else {
                getSelectedStakeholder().setPassword(encryptedNewPassword);
                getStakeholderSessionBean().editStakeholderInfo(getSelectedStakeholder());
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                        FacesMessage.SEVERITY_INFO, "Password is changed successfully", ""));
            }
        } else {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_ERROR, "ERROR: Please input the correct password we sent you", ""));
        }
    }

    public void resetPassword() throws MessagingException, UnsupportedEncodingException, NoSuchAlgorithmException {
        String generatedPassword = randomString();
        String encryptedPassword = encrypt(generatedPassword);
        String subject, standardmsg, recipient, from;

        System.out.println("generatedPassword" + generatedPassword);
        getSelectedStakeholder().setPassword(encryptedPassword);
        getStakeholderSessionBean().editStakeholderInfo(getSelectedStakeholder());
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                FacesMessage.SEVERITY_INFO, "Password is reset successfully, pls check your email", ""));
        eMailSessionBean.setPassword("emsongtronguocao");
        eMailSessionBean.setUser("is3102team32");
        subject = "Reset Password";
        standardmsg = "Your new password is " + generatedPassword;
        recipient = stakeholder.getCorpEmail();
        from = "is3102team32@gmail.com";
        //changed by Vu
        eMailSessionBean.sendMail(from, recipient, subject, standardmsg);
    }

    public void viewPaymentItem() {
        paymentItemList = transactionSessionBean.getPaymentItemOfStakeholder(stakeholder, getDate1(), getDate2());
    }
    /*Thai Duy's end*/

    public String getOldPassword() {
        return oldPassword;
    }

    public void setOldPassword(String oldPassword) {
        this.oldPassword = oldPassword;
    }

    public String getNewPassword() {
        return newPassword;
    }

    public void setNewPassword(String newPassword) {
        this.newPassword = newPassword;
    }

    public SecureRandom getRandom() {
        return random;
    }

    public void setRandom(SecureRandom random) {
        this.random = random;
    }

    public String getRetypeNewPassword() {
        return retypeNewPassword;
    }

    public void setRetypeNewPassword(String retypeNewPassword) {
        this.retypeNewPassword = retypeNewPassword;
    }

    public Date getDate1() {
        return date1;
    }

    public void setDate1(Date date1) {
        this.date1 = date1;
    }

    public Date getDate2() {
        return date2;
    }

    public void setDate2(Date date2) {
        this.date2 = date2;
    }

    public String getOutstandingBillAmount() {
        return outstandingBillAmount;
    }

    public void setOutstandingBillAmount(String outstandingBillAmount) {
        this.outstandingBillAmount = outstandingBillAmount;
    }

    public void initPaymentManagementList(PhaseEvent event) {
        System.out.println("begin method");
        stakeholder = (StakeholderEntity) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("stakeholder");
        PaymentManagementEntity payment = transactionSessionBean.getCurrentBill(stakeholder);
        System.out.println("set outstanding bill again");
        if (payment != null) {
            outstandingBillAmount = payment.getOutstandingBilling() + "";
        } else {
            outstandingBillAmount = "0";
        }
        System.out.println(outstandingBillAmount);
        this.setPaymentManagementList(stakeholderSessionBean.getBillListByStakeholderId(stakeholder.getId()));
    }

    public void payCurentBill(ActionEvent event) throws IOException {
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("purpose", "payCurrentBill");
        FacesContext.getCurrentInstance().getExternalContext().redirect("IAPaymentProcessing.xhtml");
    }

    public PackagePurchasedEntity getNextServicePackage() {
        return nextServicePackage;
    }

    public void setNextServicePackage(PackagePurchasedEntity nextServicePackage) {
        this.nextServicePackage = nextServicePackage;
    }
}
